#pragma once

#include <assert.h>

#include <chrono>
#include <functional>
#include <list>
#include <map>
#include <memory>
#include <vector>

#include "common.h"
#include "vector2d.h"

enum ECaculatePathResult {
  kCaculatePathResultNone = 0,
  kCaculatePathResultPopTarget = 1,
  kCaculatePathResultMoveToTarget = 2,
};

struct StatePathData {
  uint64_t pass_id;
  std::list<Vector2D> paths;
};

class MapSystem;
class Entity;
class MoveComponent {
 public:
  enum MoveStatus {
    kMoveStatusNone = 0,
    kMoveStatusMoving,
    kMoveStatusPathFind,
    kMoveStatusMoveCricle,
  };

 public:
  MoveComponent(MapSystem *map_system, Entity* entity);

  void Clear();
  bool IsMoving() { return move_status_ != kMoveStatusNone; }
  bool MoveTo(const Vector2D& pos,
              std::function<void(bool, EStopMoveReason)>&& cb);

  const Vector2D& GetEntityPosition() const;
  const Vector2D& GetEntityDirection() const;

  void SetEntityPosition(const Vector2D& position) const;
  void SetEntityDirection(const Vector2D& direction) const;
  bool FindPath(Vector2D start, Vector2D end);

  void OnStartMove() {}
  void OnStopMove(bool is_done, EStopMoveReason reason);

  void SetSpeed(const ZNumber& speed);

  ZNumber GetCurSpeed() { return move_speed_; }

 private:
  void CheckPreCastle();
  void HandleMove();
  void StartMove();

  bool UpdateMovePos(ZNumber& time_pass);
  bool PopMoveTarget();
  bool PopCurMoveTarget();

  void InitPathFindData(const std::list<Vector2D>& find_path_list);
  void OnPathFindResult(const std::list<Vector2D>& find_path_list);
  void DoFindPath(Vector2D start, Vector2D end, int64_t path_find_flag);

  bool IsEmplyMoveTarget();
  Vector2D* GetMoveTarget();
  Vector2D* GetPathMoveTarget();

 private:
  MapSystem *map_system_;
  Entity* entity_;
  MoveStatus move_status_;
  MSEntityComponentType component_type_;
  int64_t pre_check_time_;
  bool is_follow_move_;
  bool is_notice_;
  bool loop_move_end_check_;

  std::function<void(bool, EStopMoveReason)> move_call_back_;

  // ������·��
  std::list<Vector2D> move_cricle_paths_;
  uint32_t path_find_flag_;
  Vector2D pre_check_castle_pos_;
  ZNumber move_speed_;

  Vector2D target_position_;
  std::list<StatePathData> cur_region_paths_;
  std::vector<Vector2D> move_path_data_;
};

static uint64_t g_pass_id = 0;